package bb.lanxing.nav;

import android.app.Service;
import android.content.Intent;
import android.location.GnssStatus;
import android.location.GpsStatus;
import android.location.Location;
import android.os.IBinder;
import android.os.RemoteException;
import android.speech.tts.TextToSpeech;
import android.text.Html;
import android.text.TextUtils;

import com.baidu.mapapi.model.LatLng;
import com.github.mikephil.charting.utils.Utils;

import bb.lanxing.App;
import bb.lanxing.R;
import bb.lanxing.calc.data.GpsPoint;
import bb.lanxing.manager.SystemLocationManager;
import bb.lanxing.model.json.Route;
import bb.lanxing.model.json.RouteStep;
import bb.lanxing.util.BiCiCoorConverter;
import bb.lanxing.util.Log;
import bb.lanxing.util.map.SphericalUtil;

import java.util.Iterator;
import java.util.LinkedList;
import java.util.Locale;

/**
 * 导航服务进程
 */
public class NavigationService extends Service implements NavStatusListener {
    private LinkedList<INavigationServiceCallback> navigationServiceCallbacks;

    private TextToSpeech mTextToSpeech;

    private Location currentLocation;

    private boolean isGoogleRoute;

    private long lastYadTime;
    private long yadCount;
    private boolean playVoice = true;

    private INavigationService.Stub mBinder = new INavigationService.Stub() {
        @Override
        public boolean isNavigating() {
            return NavEngine.getInstance().isNavigating();
        }

        @Override
        public void registerCallback(INavigationServiceCallback callback) {
            if (callback == null || navigationServiceCallbacks.contains(callback)) {
                return;
            }
            navigationServiceCallbacks.add(callback);
            Log.i("nav", "registerCallback" + callback);
        }

        @Override
        public void unRegisterCallback(INavigationServiceCallback callback) {
            if (callback != null) {
                navigationServiceCallbacks.remove(callback);
            }
        }

        @Override
        public void startNavigation3(long lushuId) {
            startNav(lushuId);
        }

        @Override
        public void stopNavigation() {
            NavEngine.getInstance().stopNavigation();
        }

        @Override
        public void voiceSwitch(boolean open) {
            if (open) {
                if (playVoice) {
                    return;
                }
                playVoice = true;
                prepareTTS();
            } else if (playVoice) {
                if (mTextToSpeech != null) {
                    mTextToSpeech.stop();
                }
                playVoice = false;
            }
        }
    };

    private SystemLocationManager.GpsChangedListener gpsChangedListener = new SystemLocationManager.GpsChangedListener() {
        @Override
        public void onGpsStatusChanged(int event, GpsStatus status, GnssStatus gnssStatus) {
        }

        @Override
        public void onGpsLocationChanged(GpsPoint gpsPoint) {
            currentLocation = gpsPoint.getLocation();
            NavEngine.getInstance().onRefreshLocation(gpsPoint.getLatitude(), gpsPoint.getLongitude(), gpsPoint.getSpeed());
        }
    };

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return Service.START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        Log.i("nav", "onBind" + intent);
        if (intent != null) {
            NavEngine.getInstance().stopNavigation();
            playVoice = intent.getBooleanExtra("play_voice", true);
            prepareTTS();
            return mBinder;
        }
        stopSelf();
        return null;
    }

    public boolean startNav(long lushuId) {
        if (lushuId > 0) {
            prepareTTS();
            NavEngine.getInstance().stopNavigation();
            NavEngine.getInstance().setupRoute(lushuId);
            return true;
        }
        return false;
    }

    private void prepareTTS() {
        if (playVoice && mTextToSpeech == null) {
            mTextToSpeech = new TextToSpeech(this, status -> {
                if (status != TextToSpeech.ERROR) {
                    mTextToSpeech.setLanguage(Locale.SIMPLIFIED_CHINESE);
                    mTextToSpeech.setSpeechRate(0.5f);
                }
            });
        }
    }

    @Override
    public void onCreate() {
        super.onCreate();
        Log.i("nav", "onCreate");
        prepareTTS();
        navigationServiceCallbacks = new LinkedList<>();
        SystemLocationManager.getInstance().registerGpsChangedListener(gpsChangedListener);
        NavEngine.getInstance().setNavigationStatueListener(this);
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        SystemLocationManager.getInstance().unregisterGpsChangedListener(gpsChangedListener);
        NavEngine.release();
        if (mTextToSpeech != null) {
            mTextToSpeech.stop();
            mTextToSpeech.shutdown();
        }
    }

    private void notifyCallbacks(int type, String msg, double distance) {
        Iterator<INavigationServiceCallback> it2 = navigationServiceCallbacks.iterator();
        while (it2.hasNext()) {
            try {
                it2.next().onNavUpdate(type, msg, distance);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    private int getTurnType(RouteStep step) {
        return Route.parseManeuverType(step.getManeuver());
    }

    private String formatRouteMsg(String html) {
        return Html.fromHtml(html).toString().replaceAll("/", " ");
    }

    private String findRoadName(String html) {
        int lastIndexOf;
        int lastIndexOf2 = html.lastIndexOf("<b>");
        if (lastIndexOf2 == -1 || (lastIndexOf = html.lastIndexOf("</b>")) == -1) {
            return null;
        }
        String substring = html.substring(lastIndexOf2 + 3, lastIndexOf);
        String string = getString(R.string.nav_road);
        if (!TextUtils.isEmpty(substring) && html.endsWith(string)) {
            return getString(R.string.nav_step_changed_ahead, substring);
        }
        return findRoadName(html.substring(0, lastIndexOf2));
    }

    private String calFormatDistance(double distance) {
        int i;
        if (distance >= 1000.0d) {
            App context = App.getContext();
            return context.getString(R.string.str_fm_unit_km_cn, " " + (((((int) distance) / 100) / 10.0d) + 0.5d)).replaceAll(" ", "");
        } else if (distance < 50.0d) {
            return null;
        } else {
            if (distance < 100.0d) {
                i = (((int) distance) / 10) * 10;
            } else {
                i = (((int) distance) / 100) * 100;
            }
            App context2 = App.getContext();
            return context2.getString(R.string.str_fm_unit_m_cn, String.valueOf(i)).replaceAll(" ", "");
        }
    }

    @Override
    public void onSetup(Route route) {
        isGoogleRoute = route.getPlanSource() == Route.PlanSource.Google;
        yadCount = 0L;
        if (playVoice && mTextToSpeech != null) {
            mTextToSpeech.speak(getString(R.string.nav_start), TextToSpeech.QUEUE_FLUSH, null, null);
            Log.d("nav", "init step:");
        }
        Iterator<INavigationServiceCallback> it2 = navigationServiceCallbacks.iterator();
        while (it2.hasNext()) {
            try {
                it2.next().onNavStart();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onInitialized(RouteStep curStep, RouteStep nextStep) {
        String str;
        String formatRouteMsg = formatRouteMsg(curStep.getHtmlInstruction());
        double d = -1.0d;
        if (TextUtils.isEmpty(formatRouteMsg)) {
            str = formatRouteMsg(nextStep.getHtmlInstruction());
            if (!TextUtils.isEmpty(str)) {
                d = SphericalUtil.computeDistanceBetween(new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()), BiCiCoorConverter.common2Earth(nextStep.getStartLoc().toLatLng()));
                String calFormatDistance = calFormatDistance(d);
                if (!TextUtils.isEmpty(calFormatDistance)) {
                    formatRouteMsg = getString(R.string.nav_step_changed, calFormatDistance, str);
                }
            }
        } else {
            str = formatRouteMsg;
        }
        if (playVoice && mTextToSpeech != null) {
            mTextToSpeech.speak(formatRouteMsg, TextToSpeech.QUEUE_FLUSH, null, null);
        }
        notifyCallbacks(getTurnType(curStep), str, d);
        Log.d("nav", "first located step:" + formatRouteMsg);
    }

    @Override
    public void onStepChanged(RouteStep lastStep, RouteStep newStep, boolean isForecast) {
        if (isGoogleRoute) {
            onGoogleRouteStepChanged(lastStep, newStep, isForecast);
        } else {
            onBaiduRouteStepChanged(lastStep, newStep, isForecast);
        }
    }

    private void onGoogleRouteStepChanged(RouteStep lastStep, RouteStep newStep, boolean isForecast) {
        String str;
        String str2;
        double d;
        String str3 = null;
        double d2 = -1.0d;
        if (isForecast) {
            if (newStep != null) {
                String formatRouteMsg = formatRouteMsg(newStep.getHtmlInstruction());
                if (currentLocation != null) {
                    d2 = SphericalUtil.computeDistanceBetween(new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()), BiCiCoorConverter.common2Earth(newStep.getStartLoc().toLatLng()));
                    String calFormatDistance = calFormatDistance(d2);
                    if (!TextUtils.isEmpty(calFormatDistance)) {
                        str3 = getString(R.string.nav_step_changed, calFormatDistance, formatRouteMsg);
                    }
                }
                str = str3;
                d = d2;
                str2 = formatRouteMsg;
                if (TextUtils.isEmpty(str)) {
                    notifyCallbacks(getTurnType(newStep), str2, d);
                    Log.d("nav", "google changed step:" + str);
                }
            }
        }
    }

    private void onBaiduRouteStepChanged(RouteStep lastStep, RouteStep newStep, boolean isForecast) {
        if (isForecast && lastStep != null && newStep != null) {
            String str3 = null;
            String formatRouteMsg = formatRouteMsg(lastStep.getEndInstruction());
            double d2 = -1.0d;
            if (currentLocation != null) {
                d2 = SphericalUtil.computeDistanceBetween(new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude()),
                        BiCiCoorConverter.common2Earth(newStep.getStartLoc().toLatLng()));
                String calFormatDistance = calFormatDistance(d2);
                if (!TextUtils.isEmpty(calFormatDistance)) {
                    str3 = getString(R.string.nav_step_changed, calFormatDistance, formatRouteMsg);
                }
            }
            if (TextUtils.isEmpty(str3)) {
                notifyCallbacks(getTurnType(lastStep), formatRouteMsg, d2);
                Log.d("nav", "baidu changed step:" + str3);
            }
        }
    }

    @Override
    public void onUpdateInfo(RouteStep curStep, double distance) {
        String formatRouteMsg;
        if (distance < Utils.DOUBLE_EPSILON || curStep == null) {
            notifyCallbacks(0, getString(R.string.navigating), -1.0d);
            return;
        }
        if (isGoogleRoute) {
            formatRouteMsg = formatRouteMsg(curStep.getHtmlInstruction());
        } else {
            formatRouteMsg = formatRouteMsg(curStep.getEndInstruction());
        }
        String calFormatDistance = calFormatDistance(distance);
        String string = TextUtils.isEmpty(calFormatDistance) ? null : getString(R.string.nav_step_changed, calFormatDistance, formatRouteMsg);
        notifyCallbacks(getTurnType(curStep), formatRouteMsg, distance);
        Log.d("nav", "baidu changed step:" + string);
    }

    @Override
    public void onKeepGoing(RouteStep curStep, double distance) {
        if (playVoice && mTextToSpeech != null) {
            mTextToSpeech.speak(getString(R.string.nav_keep_going), TextToSpeech.QUEUE_FLUSH, null, null);
        }
    }

    @Override
    public void onYaw(RouteStep step) {
        long currentTimeMillis = System.currentTimeMillis();
        if (currentTimeMillis - lastYadTime > 30000L && yadCount < 5) {//c.k
            if (playVoice && mTextToSpeech != null) {
                mTextToSpeech.speak(getString(R.string.nav_yaw_of_route), TextToSpeech.QUEUE_FLUSH, null, null);
            }
            lastYadTime = currentTimeMillis;
            yadCount++;
        }
        Iterator<INavigationServiceCallback> it2 = navigationServiceCallbacks.iterator();
        while (it2.hasNext()) {
            try {
                it2.next().onNavYaw(step);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onYawBack(RouteStep step) {
        yadCount = 0L;
        if (playVoice && mTextToSpeech != null) {
            String str = null;
            if (isGoogleRoute && step != null) {
                str = findRoadName(step.getHtmlInstruction());
            }
            if (TextUtils.isEmpty(str)) {
                str = getString(R.string.nav_yaw_back);
            }
            mTextToSpeech.speak(str, TextToSpeech.QUEUE_FLUSH, null, null);
            Log.d("nav", "yaw back, step:" + str);
        }
        Iterator<INavigationServiceCallback> it2 = navigationServiceCallbacks.iterator();
        while (it2.hasNext()) {
            try {
                it2.next().onYawBack(step);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onArrived() {
        if (playVoice && mTextToSpeech != null) {
            mTextToSpeech.speak(getString(R.string.nav_end), TextToSpeech.QUEUE_FLUSH, null, null);
        }
        Iterator<INavigationServiceCallback> it2 = navigationServiceCallbacks.iterator();
        while (it2.hasNext()) {
            try {
                it2.next().onArrived();
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void onNavFailed(int code) {
        Iterator<INavigationServiceCallback> it2 = navigationServiceCallbacks.iterator();
        while (it2.hasNext()) {
            try {
                it2.next().onNavFailed(code);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
        if (code > 50) {
            NavEngine.getInstance().stopNavigation();
            stopSelf();
        }
    }
}